/*******************************************************************************
 * This file is part of Crunch Graphics.
 *
 * Crunch Graphics is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * Crunch Graphics is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * Crunch Graphics.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package com.crunch.graphics.gpu;
import javax.media.opengl.GL;

/** Encapsulates the state of the scissor test on the GPU.
 */
public class GpuScissorState extends GpuObject {
	/** Sets the state of the GPU to the state represented by this object.
	 */
	public void bind() {
		getGpuState().bind(this);
	}

	/** Sets whether the scissor test is enabled.
	 */
	public void setScissorTestEnabled(boolean e) {
		scissorTestEnabled = e;
	}

	/** Sets the scissor box position and size.
	 */
	public void setScissorBox(int x, int y, int w, int h) {
		scissorBoxX = x;
		scissorBoxY = y;
		scissorBoxWidth = w;
		scissorBoxHeight = h;
	}

	/** Returns whether the scissor test is enabled.
	 */
	public boolean isScissorTestEnabled() {
		return scissorTestEnabled;
	}

	/** Returns the scissor box x.
	 */
	public int getScissorBoxX() {
		return scissorBoxX;
	}

	/** Returns the scissor box y.
	 */
	public int getScissorBoxY() {
		return scissorBoxY;
	}

	/** Returns the scissor box position.
	 */
	public int[] getScissorBoxPosition() {
		return new int[] { scissorBoxX, scissorBoxY };
	}

	/** Returns the scissor box width.
	 */
	public int getScissorBoxWidth() {
		return scissorBoxWidth;
	}

	/** Returns the scissor box height.
	 */
	public int getScissorBoxHeight() {
		return scissorBoxHeight;
	}

	/** Returns the scissor box size.
	 */
	public int[] getScissorBoxSize() {
		return new int[] { scissorBoxWidth, scissorBoxHeight };
	}

	GpuScissorState(GpuState state) {
		super(state);
		scissorTestEnabled = false;
		scissorBoxX = 0;
		scissorBoxY = 0;
		scissorBoxWidth = 0;
		scissorBoxHeight = 0;
	}

	/** Copy constructor.
	 */
	public GpuScissorState(GpuScissorState other) {
		super(other.getGpuState());
		scissorTestEnabled = other.scissorTestEnabled;
		scissorBoxX = other.scissorBoxX;
		scissorBoxY = other.scissorBoxY;
		scissorBoxWidth = other.scissorBoxWidth;
		scissorBoxHeight = other.scissorBoxHeight;
	}

	private boolean scissorTestEnabled;             // whether the scissor test is enabled
	private int scissorBoxX, scissorBoxY;           // position of scissor box
	private int scissorBoxWidth, scissorBoxHeight;  // size of scissor box

	// compares changes against current state and apply differences
	void apply(GpuScissorState currentState) {
		currentState.scissorTestEnabled = setStateEnabled(scissorTestEnabled, currentState.scissorTestEnabled, GL.GL_SCISSOR_TEST);

		if (scissorTestEnabled) {
			if (scissorBoxX != currentState.scissorBoxX || scissorBoxY != currentState.scissorBoxY ||
					scissorBoxWidth != currentState.scissorBoxWidth || scissorBoxHeight != currentState.scissorBoxHeight) {
				getGpuState().getGl().glScissor(scissorBoxX, scissorBoxY, scissorBoxWidth, scissorBoxHeight);
				currentState.scissorBoxX = scissorBoxX;
				currentState.scissorBoxY = scissorBoxY;
				currentState.scissorBoxWidth = scissorBoxWidth;
				currentState.scissorBoxHeight = scissorBoxHeight;
			}
		}
	}

	// sets values to the current OpenGL state
	void getCurrentState() {
		scissorTestEnabled = getGpuState().getGl().glIsEnabled(GL.GL_SCISSOR_TEST);
		int[] scissorBoxResult = new int[4];
		getGpuState().getGl().glGetIntegerv(GL.GL_SCISSOR_BOX, scissorBoxResult, 0);
		scissorBoxX = scissorBoxResult[0];
		scissorBoxY = scissorBoxResult[1];
		scissorBoxWidth = scissorBoxResult[2];
		scissorBoxHeight = scissorBoxResult[3];
	}
}